﻿using ICCardHelper;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ControllerClient
{
    class PSAMHelper
    {

        private  static string TAG = "PsamTool";
        string card = "01";
        int baud = 9600;
        string cmdVoltage = "6D";
        private byte[] psamID = new byte[4];//00030DC8
        static string PSAMReaderName = ConfigHelper.GetAppConfig("PSAMReaderName");
        static PCSCReader psam = new PCSCReader(PSAMReaderName);
       

        //获取信息 GET_INFO  8010010015,获取设备id
        public string getPSAMinfo()
        {
           
            
           // return mPSAM.executeCmd("00", "8010010015").Substring(0, 8);
           return psam.sendAPDU("8010010015").Substring(0, 8);
        }

        //用户验证(VERIFY_USER)   80200000+数据域长度+用户验证信息(用户ID+用户PIN码)
        public bool verifyUser()
        {
            psam.upPower();
            string userIDStr = "5053414D49303031";
            string userPINStr = "4D494D49535F5053414D5F55534552";
            byte[] userID = HexUtils.strToHexByte(userIDStr);
            byte[] userPIN = HexUtils.strToHexByte(userPINStr);
            byte[] length = new byte[1];
            length[0] = (byte)(userID.Length + userPIN.Length);
            //LogHelper.Debug("length" + HexUtils.byteToHexStr(length));
            string cmd = "80200000" + "17" + userIDStr + userPINStr;
            // LogHelper.Debug("verifyUsercmd=" + cmd);
            string cmdrs = psam.sendAPDU( cmd);
            // LogHelper.Debug( "verifyUserRs=" + cmdrs);
            if (cmdrs == null)
            {
                return false;
            }
            if (cmdrs.EndsWith("9000"))
            {
                return true;
            }
            return false;
        }

        //获取PSAM数据证书第一部分  8010020000
        //public string getPSAMCertifiPart1()
        //{
        //    string CertifiPart1 = "";
        //    string cmd = "8010020080";
        //     LogHelper.Debug(TAG, "getPSAMCertifiPart1cmd=" + cmd);
        //    string cmdrs = mPSAM.executeCmd("00", cmd);
        //    if (cmdrs == null)
        //    {
        //        return null;
        //    }
        //     LogHelper.Debug(TAG, "getPSAMCertifiPart1rs=" + cmdrs);
        //    if (cmdrs.EndsWith("6180"))
        //    {
        //        CertifiPart1 = cmdrs.Substring(0, cmdrs.Length - 4);
        //        cmdrs = getResponse(cmdrs.Substring(cmdrs.Length - 2, cmdrs.Length));
        //        if (cmdrs == null)
        //        {
        //            return null;
        //        }
        //        CertifiPart1 += cmdrs;
        //    }

        //    //        if (cmdrs.endsWith("6180")) {
        //    //            CertifiPart1 = cmdrs.Substring(0, cmdrs.length() - 4);
        //    //            cmd = "00C0000080";
        //    //            cmdrs = mPSAM.executeCmd("00", cmd);
        //    //            if (cmdrs == null) {
        //    //                return null;
        //    //            }
        //    //            CertifiPart1 += cmdrs;
        //    //        }
        //    return CertifiPart1;
        //}

        //public string getPSAMCertifiPart2()
        //{
        //    string CertifiPart2 = "";
        //    string cmd = "8010020136";
        //     LogHelper.Debug(TAG, "getPSAMCertifiPart2cmd=" + cmd);
        //    string cmdrs = mPSAM.executeCmd("00", cmd);
        //     LogHelper.Debug(TAG, "getPSAMCertifiPart2rs=" + cmdrs);
        //    if (cmdrs == null)
        //    {
        //        return null;
        //    }

        //    if (cmdrs.EndsWith("6134"))
        //    {
        //        CertifiPart2 = cmdrs.Substring(0, cmdrs.Length - 4);
        //        cmdrs = getResponse(cmdrs.Substring(cmdrs.Length - 2, cmdrs.Length));
        //        if (cmdrs == null)
        //        {
        //            return null;
        //        }
        //        CertifiPart2 += cmdrs;
        //    }

        //    //        if (cmdrs.endsWith("6134")) {
        //    //            CertifiPart2 = cmdrs.Substring(0, cmdrs.length() - 4);
        //    //            cmd = "00C0000034";
        //    //            cmdrs = mPSAM.executeCmd("00", cmd);
        //    //            if (cmdrs == null) {
        //    //                return null;
        //    //            }
        //    //            CertifiPart2 += cmdrs;
        //    //        }
        //    return CertifiPart2;
        //}
        //生成电子签封交互指令(GEN_ELS_CMD)
        //8030 + 交互指令 + 00 + 数据长度 + 数据(交互指令DATA)（EPC长度 + EPC + 交互指令数据长度 + 交互指令数据（交互指令 + 随机数））
        public string genElsCmd(string cmdType, string epc, string data)
        {
            byte[] epcb = HexUtils.strToHexByte(epc);
            byte[] datab = HexUtils.strToHexByte(data);
            byte[] epcLen = { (byte)epcb.Length };
            byte[] dataLen = { (byte)datab.Length };
            byte[] allLen = { (byte)(epcb.Length + datab.Length + 2) };

            string cmd = "8030" + cmdType + "00"
                    + HexUtils.byteToHexStr(allLen)
                    + HexUtils.byteToHexStr(epcLen)
                    + epc
                    + HexUtils.byteToHexStr(dataLen)
                    + data;
            //+"00";
            // LogHelper.Debug( "genElsCmd=" + cmd);
            string cmdrs = psam.sendAPDU(cmd);

            if (cmdrs == null)
            {
                return null;
            }
             LogHelper.Debug( "genElsRs=" + cmdrs);
            if (cmdrs.StartsWith("61"))
            {
                cmdrs = getResponse(cmdrs.Substring(2));
                if (cmdrs == null)
                {
                    return null;
                }
            }
            return cmdrs;

        }

        public string excute(string cmd)
        {
            string cmdrs = psam.sendAPDU( cmd);
            {
                if (cmdrs.StartsWith("61"))
                {
                    cmdrs = getResponse(cmdrs.Substring(2));
                    if (cmdrs == null)
                    {
                        return null;
                    }
                }
            }
            return cmdrs;
        }
        public string getResponse(string len)
        {
            string cmd = "00C00000" + len;
             LogHelper.Debug( "getResponsecmd=" + cmd);
            string cmdrs = psam.sendAPDU( cmd);
            // LogHelper.Debug( "getResponseRs=" + cmdrs);
            if (cmdrs == null)
            {
                return null;
            }
            if (cmdrs.EndsWith("9000"))
            {
                return cmdrs;
            }
            return cmdrs;
        }

        //开锁写物流指令0x05
        //数据(交互指令DATA):张数（2字节）+ 操作员1(4字节) + 操作员2(4字节) + 操作时间(4字节) + 手持机ID(PSAM卡ID后20bit) + 位置序号(4bit) + 随机数(4字节)+保留(1字节)
        public string genCloseWriteElsCmd(string epc, int number, byte[] operator1, byte[] operator2, string dateTime)
        {
            string dataStr;
            byte[] data;
            byte[] dateTimeByte;
            byte[] numberBytes = new byte[2];
            string psamIDStr;
            string deviceID;
            string cmdType;

            numberBytes[0] = (byte)(number / 256);
            numberBytes[1] = (byte)(number % 256);

            long timer = TimerHelper.GetTimeStamp();
            dateTimeByte = HexUtils.ToBytes(timer);
            psamIDStr = getPSAMinfo().Substring(3, 8);
            psamIDStr = psamIDStr + "0";
            deviceID = psamIDStr;
            dataStr = HexUtils.byteToHexStr(numberBytes)
                    + HexUtils.byteToHexStr(operator1)
                    + HexUtils.byteToHexStr(operator2)
                    + HexUtils.byteToHexStr(dateTimeByte)
                    + deviceID
                    + "00000000"
                    + "00";
            cmdType = "04";
            return genElsCmd(cmdType, epc, dataStr);

        }
        //开锁写物流指令0x04
        //数据(交互指令DATA):张数（2字节）+ 操作员1(4字节) + 操作员2(4字节) + 操作时间(4字节) + 手持机ID(PSAM卡ID后20bit) + 位置序号(4bit) + 随机数(4字节)+保留(1字节)
        public string genOpenWriteElsCmd(string epc, int number, byte[] operator1, byte[] operator2, string dateTime)
        {
            string dataStr;
            byte[] data;
            byte[] dateTimeByte;
            byte[] numberBytes = new byte[2];
            string psamIDStr;
            string deviceID;
            string cmdType;

            numberBytes[0] = (byte)(number / 256);
            numberBytes[1] = (byte)(number % 256);

            //long timer = TimerHelper.GetTimeStamp();
            dateTimeByte = dateTimeToByte();
            psamIDStr = getPSAMinfo().Substring(3, 8);
            psamIDStr = psamIDStr + "0";
            deviceID = psamIDStr;
            dataStr = HexUtils.byteToHexStr(numberBytes).Substring(0,2)
                    + HexUtils.byteToHexStr(operator1)
                    + HexUtils.byteToHexStr(operator2)
                    + HexUtils.byteToHexStr(dateTimeByte)
                    + deviceID
                    + "00000000"
                    + "00";
            cmdType = "05";
            return genElsCmd(cmdType, epc, dataStr);

        }
        //关锁指令0x02
        //张数（2字节）+ 操作员1(4字节) + 操作员2(4字节) + 操作时间(4字节) + 手持机ID(PSAM卡ID后20bit) + 位置序号(4bit) + 随机数(4字节)+保留(1字节)
        public string genCloseElsCmd(string epc, int number, byte[] operator1, byte[] operator2)
        {
            string dataStr;
            byte[] data;
            byte[] dateTimeByte;
            byte[] numberBytes = new byte[2];
            string psamIDStr;
            string deviceID;
            string cmdType;

            numberBytes[0] = (byte)(number / 256);
            numberBytes[1] = (byte)(number % 256);
           
            dateTimeByte = dateTimeToByte();
            psamIDStr = getPSAMinfo().Substring(3, 5);
            psamIDStr = psamIDStr + "0";
            deviceID = psamIDStr;
            dataStr = HexUtils.byteToHexStr(numberBytes)
                    + HexUtils.byteToHexStr(operator1)
                    + HexUtils.byteToHexStr(operator2)
                    + HexUtils.byteToHexStr(dateTimeByte)
                    + deviceID
                    + "00000000"
                    + "00";
            cmdType = "02";
            return genElsCmd(cmdType, epc, dataStr);

        }
        //开锁指令0x03
        //数据(交互指令DATA):张数（2字节）+ 操作员1(4字节) + 操作员2(4字节) + 操作时间(4字节) + 手持机ID(PSAM卡ID后20bit) + 位置序号(4bit) + 随机数(4字节)+保留(1字节)
        public string genOpenElsCmd(string epc, int number, byte[] operator1, byte[] operator2)
        {
            string dataStr;
            byte[] data;
            byte[] dateTimeByte;
            byte[] numberBytes = new byte[2];
            string psamIDStr;
            string deviceID;
            string cmdType;

            numberBytes[0] = (byte)(number / 256);
            numberBytes[1] = (byte)(number % 256);

            
            dateTimeByte = dateTimeToByte();
            //LogHelper.Debug("deviceid" + getPSAMinfo().Substring(3, 5));
            psamIDStr = getPSAMinfo().Substring(3, 5);
            psamIDStr = psamIDStr + "0";
            deviceID = psamIDStr;
            dataStr = HexUtils.byteToHexStr(numberBytes)
                    + HexUtils.byteToHexStr(operator1)
                    + HexUtils.byteToHexStr(operator2)
                    + HexUtils.byteToHexStr(dateTimeByte)
                    + deviceID
                    + "00000000"
                    + "00";
            cmdType = "03";
            //LogHelper.Debug("dataStr" + dataStr);
            return genElsCmd(cmdType, epc, dataStr);
        }

        //获取 RFID 访问密码(GET_RFID_PWD)   80360000 + 数据长度 + EPC数据 + 00
        public string getRFIDPassword(string epc)
        {
            byte[] length = new byte[1];
            length[0] = (byte)(epc.Length / 2);

            string cmd = "80360000" + HexUtils.byteToHexStr(length).Substring(0,1) + epc;
             LogHelper.Debug(TAG, "getRFIDPasswordcmd=" + cmd);
            string cmdrs = psam.sendAPDU( cmd);
             LogHelper.Debug(TAG, "getRFIDPasswordrs=" + cmdrs);
            if (cmdrs.StartsWith("61"))
            {
                cmdrs = getResponse(cmdrs.Substring(2));

                if (cmdrs == null)
                {
                    return null;
                }
            }
            return cmdrs;

        }

        public static byte[] dateTimeToByte()
        {

            ulong DateTime1;
            ulong year = (ulong.Parse(DateTime.Now.Year.ToString())) % 100;
            ulong month = ulong.Parse(DateTime.Now.Month.ToString());
            ulong day = ulong.Parse(DateTime.Now.Day.ToString());
            ulong hour = ulong.Parse(DateTime.Now.Hour.ToString());
            ulong minute = ulong.Parse(DateTime.Now.Minute.ToString());
            ulong second = ulong.Parse(DateTime.Now.Second.ToString());
            byte[] DateTimeb = new byte[4];
           LogHelper.Debug("year=" + year + "month=" + month + "day=" + day + "hour=" + hour + "minute=" + minute + "second=" + second);
            //2019-4-4 16:52:21
            DateTime1 = ((year << 26) | (month << 22) | (day << 17) | (hour << 12) | (minute << 6) | second);
            DateTimeb[0] = (byte)(DateTime1 >> 24);
            DateTimeb[1] = (byte)(DateTime1 >> 16);
            DateTimeb[2] = (byte)(DateTime1 >> 8);
            DateTimeb[3] = (byte)(DateTime1);
            return DateTimeb;
        }
    }
}
